package com.gee.spring.cloud.data.transform.core.dispatch;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.HexUtil;
import com.gee.spring.cloud.common.core.domain.center.config.ChannelHandlerConfigDto;
import com.gee.spring.cloud.common.core.domain.frame.CstpWrapper;
import com.gee.spring.cloud.common.core.domain.socket.IChannelHandlerConf;
import com.gee.spring.cloud.common.core.domain.socket.SocketType;
import com.gee.spring.cloud.common.core.entity.center.config.TransformDsl;
import com.gee.spring.cloud.common.core.enums.SendReceive;
import com.gee.spring.cloud.common.core.enums.YesNo;
import com.gee.spring.cloud.common.starter.socket.SocketHolder;
import com.gee.spring.cloud.data.transform.core.center.config.handler.TransformDslHandler;
import com.gee.spring.cloud.data.transform.core.util.DslUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

import static com.gee.spring.cloud.data.transform.core.constant.TransformConstant.DLS_TO_OUTER_METHOD_NAME;

/**
 * @author gepengjun
 * @since 2024/3/18 16:21
 */
@Component
@Slf4j
public class CenterDataDispatcher {

    @Autowired
    private BaseDataDispatcher baseDataDispatcher;

    @Autowired
    private SocketManager socketManager;

    @Autowired
    private TransformDslHandler transformDslHandler;

    public void dispatch(CstpWrapper cstpWrapper) {
        socketManager.getSocketConfigDtoMap().values().forEach(socketConfigDto -> {
            if (socketConfigDto.getSocketType().equals(SocketType.TCP_SERVER.name())){
                if (CollectionUtil.isNotEmpty(socketConfigDto.getClientConfigDtoMap())){
                    socketConfigDto.getClientConfigDtoMap().values().forEach(socketClientConfigDto -> {
                        doDispatch(cstpWrapper, socketConfigDto.getId(), socketClientConfigDto.getChannelHandlerConfMap());
                    });
                }
            }else {
                doDispatch(cstpWrapper, socketConfigDto.getId(), socketConfigDto.getChannelHandlerConfMap());
            }
        });
    }

    private void doDispatch(CstpWrapper cstpWrapper, Long socketConfigId, Map<Long, IChannelHandlerConf> channelHandlerConfMap) {
        channelHandlerConfMap.values().stream()
                .map(iChannelHandlerConf -> (ChannelHandlerConfigDto)iChannelHandlerConf)
                .filter(channelHandlerConfigDto -> channelHandlerConfigDto.getEnable() == YesNo.YES.getCode()
                        && channelHandlerConfigDto.getSendReceive().equals(SendReceive.SEND.name()))
                .forEach(channelHandlerConfigDto -> {
                    //开启了信道卫星过滤
                    if (channelHandlerConfigDto.getEnableChannelFilterSate() == YesNo.YES.getCode()
                            && channelHandlerConfigDto.getFilterSateList().stream()
                            .noneMatch(satellite -> satellite.getSateIdentity() == cstpWrapper.getTid())){
                        //log.warn("信道卫星过滤未通过,卫星识别字：{}", HexUtil.toHex(cstpWrapper.getTid()));
                        return;
                    }
                    //开启了信道设备过滤
                    if (channelHandlerConfigDto.getEnableChannelFilterSate() == YesNo.YES.getCode()
                            && channelHandlerConfigDto.getFilterSateList().stream()
                            .noneMatch(satellite -> satellite.getSateIdentity() == cstpWrapper.getTid())){
                        //log.warn("信道设备过滤未通过,设备识别字：{}", HexUtil.toHex(cstpWrapper.getSid()));
                        return;
                    }
                    //信息格式
                    if (channelHandlerConfigDto.getFilterFrameList().stream()
                            .noneMatch(frame -> frame.getBid() == cstpWrapper.getBid())){
                        //log.warn("信道信息格式过滤未通过,信息格式：{}", HexUtil.toHex(cstpWrapper.getBid()));
                        return;
                    }
                    byte[] bytes = transToOuterFrame(channelHandlerConfigDto.getTransformDslId(), cstpWrapper);
                    if (log.isDebugEnabled()){
                        log.debug("原数据: {}, \r\n转换为外部数据: {}", cstpWrapper, HexUtil.encodeHexStr(bytes));
                    }
                    SocketHolder.writeAndFlush(socketConfigId, channelHandlerConfigDto.getId(), bytes);
                });
    }

    private byte[] transToOuterFrame(Long dslId, CstpWrapper cstpWrapper) {
        TransformDsl transformDsl = transformDslHandler.getById(dslId);
        try {
            Object result = DslUtil.invokeStatic(DLS_TO_OUTER_METHOD_NAME, transformDsl.getDslScript(),
                    baseDataDispatcher.getOrg(), baseDataDispatcher.getOrgCenter(), cstpWrapper);
            return (byte[]) result;
        } catch (Exception e) {
            String format = String.format("执行转换为外部帧脚本出错, 脚本名称: %s", transformDsl.getDslName());
            throw new RuntimeException(format, e);
        }
    }
}
